#include <stdio.h>
#include <graphics.h>
#include <conio.h>
#include <vector>

using namespace std;

#define WIN_WINDTH 1024
#define WIN_HEIGHT 740
#define OBSTACLE_COUNT 100


typedef enum {

	TORTOISE,//乌龟
	LION,//狮子
	HOOK1,
	HOOK2,
	HOOK3,
	HOOK4,
	OBSTACLE_TYPE_COUNT
} obstacle_type;

typedef struct obstacle {
	obstacle_type type;//障碍物类型
	int x, y;//障碍物坐标
	int imgIndex;
	int speed;//速度
	int power;
	bool exist;//是否存在
	bool hited = false;
} obstacle_t;

IMAGE imgBgs[3];
IMAGE imgHero[12];
IMAGE imgHeroDown[2];

int bgX[3];
int bgSpeed[3] = { 4,8,16 };
int speeds[5] = { 4,5,0,0,0 };
int powers[5] = { 9,20,20,20,20 };
int heroX = 0;
int heroY = 0;
int imageIndex = 0;
int jumpHeightMax = 0;
int jumpOff = -14;
int heroBlood = 100;

bool jumpFlag = false;
bool heroDown = false;
bool refreshFlag = false;


vector<vector<IMAGE>> obstacleImgs;



obstacle_t obstacles[OBSTACLE_COUNT];


int calHeroY() {
	return 600 - imgHero[0].getheight();
}

int calHeroX() {
	return  WIN_WINDTH * 0.5 - imgHero[0].getwidth() * 0.5;;
}

void init() {
	initgraph(WIN_WINDTH, WIN_HEIGHT);

	char imgName[64];

	for (int i = 0; i < 3; i++)
	{
		sprintf_s(imgName, "rep/%04d.png", i + 1);
		loadimage(&imgBgs[i], imgName);
		bgX[i] = 0;
	}

	for (size_t i = 0; i < 12; i++)
	{
		sprintf_s(imgName, "rep/%03d.png", i + 1);
		loadimage(&imgHero[i], imgName);
	}
	heroX = calHeroX();
	heroY = calHeroY();

	jumpHeightMax = heroY - 120;

	IMAGE imgTort;
	loadimage(&imgTort,"rep/t1.png");
	vector<IMAGE> imgTortArray;
	imgTortArray.push_back(imgTort);
	obstacleImgs.push_back(imgTortArray);

	
	vector<IMAGE> imgLionArray;
	IMAGE imgLion;
	char name[64];
	for (int i = 0; i < 6; i++)
	{
		sprintf_s(name, "rep/p%d.png", i + 1);
		loadimage(&imgLion, name);
		imgLionArray.push_back(imgLion);
	}
	obstacleImgs.push_back(imgLionArray);
	
	for (int i = 0; i < OBSTACLE_COUNT; i++) {
		obstacles[i].exist = false;
	}
	loadimage(&imgHeroDown[0], "rep/01.png");
	loadimage(&imgHeroDown[1], "rep/02.png");
	heroDown = false;

	
	IMAGE imgH;

	for (int i = 0; i < 4; i++)
	{
		vector<IMAGE> imgHookArry;
		sprintf_s(name, "rep/h%d.png", 1 + 1);
		loadimage(&imgH, name, 80, 560, true);
		imgHookArry.push_back(imgH);

		obstacleImgs.push_back(imgHookArry);
	}
	
}

void updateBg() {
	putimage(bgX[0], 0, &imgBgs[0]);
	putimage(bgX[1], 322, &imgBgs[1]);
	putimage(bgX[2], 572, &imgBgs[2]);
}

void createObstacle() {
	int i=0;
	for (int i = 0; i < OBSTACLE_COUNT; i++)
	{
		if (!obstacles[i].exist) {
			break;
		}
	}

	if (i >= OBSTACLE_COUNT) {
		return;
	}

	if (obstacles[i].exist) {
		return;
	}
	obstacles[i].exist = true;
	obstacles[i].hited = false;
	obstacles[i].imgIndex = rand()%2;
	obstacles[i].type = (obstacle_type)(rand() % OBSTACLE_TYPE_COUNT);
	obstacles[i].x = WIN_WINDTH;
	if (obstacles[i].type<HOOK1 || obstacles[i].type>HOOK4) {
		obstacles[i].y = 600 - obstacleImgs[obstacles[i].type][0].getheight();
	}
	else {
		obstacles[i].y = 0;
	}
	
	obstacles[i].speed = speeds[obstacles[i].type];
	obstacles[i].power = powers[obstacles[i].type];

}

boolean rectIntersect(int x01, int y01, int x02, int y02, int x11, int y11, int x12, int y12) {
	int zx = abs(x01 + x02 - x11 - x12);
	int x = abs(x01 - x02) + abs(x11 - x12);
	int zy = abs(y01 + y02 - y11 - y12);
	int y = abs(y01 - y02) + abs(y11 - y12);

	return (zx <= x && zy <= y);
}
/*
void playSound(const char* name) {
	static int index = 1;
	char cmd[512];
	if (1 == index) {
		sprintf_s(cmd, sizeof(cmd), "play %s-1", name);
		mciSendString(cmd, 0, 0, 0);
		sprintf_s(cmd, sizeof(cmd), "play %s-2", name);
		mciSendString(cmd, 0, 0, 0);
		index++;
	}
	else if (index == 2) {
		sprintf_s(cmd, sizeof(cmd), "play %s-2", name);
		mciSendString(cmd, 0, 0, 0);
		sprintf_s(cmd, sizeof(cmd), "play %s-1", name);
		mciSendString(cmd, 0, 0, 0);
		sprintf_s(cmd, sizeof(cmd), "open %s alias %s-1", name,name);
		mciSendString(cmd, 0, 0, 0);
		index = 1;
	}
}*/


void checkHit() {
	for (int i = 0; i < OBSTACLE_COUNT; i++)
	{
		if (obstacles[i].exist && obstacles[i].hited == false) {
			int a1x, a1y, a2x, a2y;
			int off = 0;
			if (heroDown) {
				a1x = heroX + off;
				a1y = 400 - imgHeroDown[imageIndex].getheight();
				a2x = heroX + imgHeroDown[imageIndex].getwidth() - off;
				a2y = 400;
			}
			else {
				a1x = heroX + off;
				a1y = heroY + off;

				a2x = heroX + imgHero[imageIndex].getwidth() - off;
				a2y = heroY + imgHero[imageIndex].getheight() - off;
				
			}

			IMAGE img = obstacleImgs[obstacles[i].type][obstacles[i].imgIndex];
			int b1x = obstacles[i].x + off;
			int b1y = obstacles[i].y + off;
			int b2x = obstacles[i].x + img.getwidth() - off;
			int b2y = obstacles[i].y + img.getheight() - off;

			if (rectIntersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)) {
				heroBlood -= obstacles[i].power;
				printf("血量剩余 %d \n", heroBlood);
				//playSound(""); //声音
				obstacles[i].hited = true;
			}
		}
	}
}

void updatePosition() {
	for (int i = 0; i < 3; i++) {
		bgX[i] -= bgSpeed[i];
		
		if (bgX[i] < -WIN_WINDTH+100) {
			bgX[i] = 0;
		}
	}
	

	if (jumpFlag) {
		if (heroY < jumpHeightMax) {
			jumpOff = 14;
		}
	

		heroY += jumpOff;

		if (heroY > calHeroY()) {
			heroY = calHeroY();
			jumpFlag = false;
			jumpOff = -14;
		}
	}
	else if (heroDown) {
		static int count = 0;
		int delays[2] = { 4,10 };
		count++;
		if (count >= delays[imageIndex]) {
			imageIndex++;

			if (imageIndex > 1) {
				imageIndex = 0;
				heroDown = false;
			}
		}
	}
	else {
		imageIndex = (imageIndex + 1) % 12;
	}

	static int frameCount = 0;
	static int enemyFre = 10;
	frameCount++;
	if (frameCount > enemyFre) {
		frameCount = 0;
		enemyFre = 10 + rand() % 10;
		createObstacle();
	}

	for (int i = 0; i < OBSTACLE_COUNT; i++)
	{	
		if (obstacles[i].exist) {
			obstacles[i].x -= obstacles[i].speed + bgSpeed[2];
			if (obstacles[i].x < -obstacleImgs[obstacles[i].type][0].getwidth()*2) {
				obstacles[i].exist = false;
			}
			int len = obstacleImgs[obstacles[i].type].size();
			obstacles[i].imgIndex = (obstacles[i].imgIndex + 1) % len;
		}
	}
	//玩家和障碍物碰撞处理
	checkHit();
}

void jumpHero() {
	jumpFlag = true;
	refreshFlag = true;
}

void downHero() {
	refreshFlag = true;
	heroDown = true;
	imageIndex = 0;
}

void keyEvent() {

	if (_kbhit()) {
  		char c = _getch();
		if (c == ' ') {
			jumpHero();
		}
		else if ('a' == c) {
			downHero();
		}
	}
}

int getDelay() {
	static unsigned long long lastTime = 0;
	unsigned long long currentTime = GetTickCount();
	if (0 == lastTime) {
		lastTime = currentTime;
		return 0;
	}
	else {
		int ret = currentTime - lastTime;
		lastTime = currentTime;
		return ret;
	}
}

void updateEnemy() {
	for (int i = 0; i < OBSTACLE_COUNT; i++)
	{
		if (obstacles[i].exist) {
			putimage(obstacles[i].x, obstacles[i].y,&obstacleImgs[obstacles[i].type][obstacles[i].imgIndex]);
		}
	}
}

void updateHero() {
	if (heroDown) {
		int y = 550 - imgHeroDown[imageIndex].getheight();
		putimage(heroX, y, &imgHeroDown[imageIndex]);
	}
	else {
		putimage(heroX, heroY, &imgHero[imageIndex]);
	}
}

int main(void) {
	init();

	int time = 0;
	while (1) {
		keyEvent();
		time += getDelay();
		if (time >= 400) {
			time = 0;
			refreshFlag = true;
		}

		if (refreshFlag) {
			refreshFlag = false;
			BeginBatchDraw();
			updateBg();
			//putimage(heroX, heroY, &imgHero[imageIndex]);
			updateHero();
			updateEnemy();
			EndBatchDraw();

			updatePosition();
		}
	

		//Sleep(400);
	}

	
	

	system("pause");
}